home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 June: Reference Library / Dev.CD Jun 94.toast / Periodicals / develop / develop Issue 9 / develop 9 code / Tracks / init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-16  |  14.0 KB  |  540 lines  |  [TEXT/MPS ]

  1. /**************************************************************
  2. Copyright 1990, 1991 Orion Network Systems, Inc. All Rights Reserved.
  3. **************************************************************/
  4. #include <Memory.h>
  5. #include <Resources.h>
  6. #include <Files.h>
  7. #include <Types.h>
  8. #include <Devices.h>
  9. #include <Events.h>
  10. #include <SysEqu.h>        /* FOR PORTABLE BUG */
  11. #include <Strings.h>
  12. #include <Errors.h>
  13. #include <Notification.h>
  14. #include <OSUtils.h>
  15. #include <Folders.h>
  16.  
  17. #include "init.h"
  18. #include "traceModule.h"
  19.  
  20. pascal void InitMain()
  21. {
  22. short err;
  23. short refnum;
  24. StringPtr traceDrvrName;
  25. Handle dceHandle; /* FOR PORTABLE BUG */
  26. Handle drvrHandle; /* FOR PORTABLE BUG */
  27. Ptr entryPtr; /* FOR PORTABLE BUG */
  28. char myKeyMap[16];
  29. register short iconID = InactiveIconID;
  30. saveTypeHandle    userPrefsHandle;
  31. short sysFolderRefNum=0;
  32. short prefsVolRef;
  33. Boolean    shiftHeldDown;
  34. Boolean    loadTraceDriver;
  35. SysEnvRec environment;
  36. Handle    drvrName;    // String pointer to target driver's name..
  37.  
  38.     err = SysEnvirons(1,&environment);
  39.     if (err == noErr) 
  40.         sysFolderRefNum = environment.sysVRefNum;else sysFolderRefNum = 0;        // Get the sys folder vref
  41.         
  42.     if (environment.systemVersion >= 0x0700)
  43.         prefsVolRef = GetFolderVol(kPreferencesFolderType);
  44.     else prefsVolRef = sysFolderRefNum;
  45.  
  46.     userPrefsHandle = GetUserPrefs(prefsVolRef, &drvrName);
  47.  
  48.     if (userPrefsHandle != nil)
  49.         loadTraceDriver = ((**userPrefsHandle).fTraceOnStartup != 0);
  50.     else loadTraceDriver = false;
  51.     
  52.     /* Check if the shift key is down - if it is then DO NOT install: */
  53.     GetKeys((KeyMap) myKeyMap);
  54.     shiftHeldDown = myKeyMap[shiftKeyCode / 8] & (0x01 << (shiftKeyCode % 8));
  55.     
  56.     if (shiftHeldDown)
  57.         {
  58.         // Driver will be installed when the cdev is first opened...
  59.         iconID = InactiveIconID;
  60.         }        
  61.     else
  62.         {
  63.     
  64.         /* Install and open the driver */
  65.         
  66.         traceDrvrName = "\p.TRACE";
  67.         err = InstallDriver(traceDrvrName);
  68.         
  69.         if (err == noErr)
  70.             err = OpenDriver(traceDrvrName, &refnum);    
  71.     
  72.         /* FOR PORTABLE BUG - after _Open on Mac portable, driver has been unlocked */
  73.         /* on the system heap, even though dNeedLock is set in the driver flags !!! */
  74.         
  75.         if (err == noErr)
  76.             {
  77.             entryPtr = *((Ptr *) UTableBase);
  78.             entryPtr += ((~refnum) * 4); 
  79.             dceHandle = *((Handle *) entryPtr);
  80.             drvrHandle = (Handle) ((DCtlEntry *) *dceHandle)->dCtlDriver;
  81.             if (drvrHandle != nil) /* Just in case */
  82.             HLock(drvrHandle);
  83.             if (loadTraceDriver)
  84.                 iconID = InvokeTrace(refnum, prefsVolRef, userPrefsHandle, drvrName);
  85.             }
  86.         else    // Open Driver failed..
  87.             {
  88.                 iconID = ErrorIconID;        
  89.                 InitNotify(err,0);        // Install STR Resource ID 0 
  90.             }
  91.         DisposHandle((Handle) userPrefsHandle);
  92.         }
  93.     /* Display ShowINIT icon */
  94.  
  95.     ShowINIT(iconID, -1); /* Use moveX = -1 to move the default amount */
  96.         
  97.     return;
  98.  
  99. }
  100.  
  101. saveTypeHandle GetUserPrefs(short prefsVolRef, Handle *driverDotName)
  102. {
  103. register saveTypeHandle    hSave = nil;
  104. short PrefsResRefNum;
  105. register short err;
  106. Handle PStrHand, targetAppName;
  107.  
  108.     *driverDotName = nil;        // In case we don't get a chance to get the real one.
  109.     
  110.     PStrHand = GetResource('STR ', -4063);        // Get name of Pref. file from within
  111.     if (PStrHand != nil) 
  112.     {
  113.         PrefsResRefNum = OpenRFPerm((const Str255)*PStrHand, prefsVolRef, fsRdWrPerm);
  114.         err = ResError();
  115.         ReleaseResource(PStrHand);
  116.         if (err == noErr)
  117.         {
  118.             hSave = (saveTypeHandle) GetResource(kPrefResType, kPrefResID);
  119.             if (hSave != nil) 
  120.                 DetachResource((Handle)hSave);        // Detach so we can close now...
  121.             
  122.             targetAppName = GetResource('kDRp', 128);
  123.             if (targetAppName != nil) 
  124.             {
  125.                 *driverDotName = GetTargAppStuff(targetAppName);
  126.                 ReleaseResource(targetAppName);
  127.             } 
  128.             
  129.             CloseResFile(PrefsResRefNum);
  130.             err = ResError();
  131.         } 
  132.     }
  133.     return hSave;        // May be nil, as might *driverDotName
  134. }
  135.  
  136. Handle GetTargAppStuff(Handle targetAppName)
  137. {
  138. short infoFileRefNum, err;
  139. Handle driverDotName = nil;
  140.  
  141.     if (targetAppName != nil)
  142.     {
  143.         HLock(targetAppName);
  144.  
  145.         infoFileRefNum = OpenRFPerm(*targetAppName, GetFolderVol(kSystemFolderType), fsRdWrPerm);
  146.         if (infoFileRefNum == -1) 
  147.         infoFileRefNum = OpenRFPerm(*targetAppName, GetFolderVol(kExtensionFolderType), fsRdWrPerm);
  148.         if (infoFileRefNum == -1) 
  149.         infoFileRefNum = OpenRFPerm(*targetAppName, GetFolderVol(kControlPanelFolderType), fsRdWrPerm);
  150.         HUnlock(targetAppName);
  151.         err = ResError();
  152.         if (err == noErr)
  153.         {
  154.             // Get DotDriverName -- eg  ".ASNA"
  155.     
  156.             driverDotName = GetResource('DrvN', 128);
  157.             err = ResError();
  158.             if (driverDotName != nil) 
  159.             {    
  160.                 DetachResource(driverDotName);
  161.             }
  162.             else 
  163.             {
  164.                 // nil will be returned... which is okay
  165.             }
  166.  
  167.             CloseResFile(infoFileRefNum);
  168.             err = ResError();
  169.         } 
  170.     }
  171.     return driverDotName;
  172.     
  173. }
  174.  
  175. static void Append(char *pstr, char *addstr, short addlen)
  176. {
  177.     register short plen;
  178.     
  179.     plen = *pstr;
  180.     
  181.     if ((addlen + plen) > 255)
  182.         addlen = 255 - plen;
  183.     
  184.     BlockMove((char *) addstr, (char *) (pstr + plen + 1), addlen);
  185.     
  186.     *pstr += addlen;
  187.     
  188.     return;    
  189.     
  190. }
  191.  
  192. void InitNotify(short err, short ResourceID)
  193. {
  194. NMRec *recPtr;
  195. char *errstr;
  196. register char *n;
  197. short numlen;
  198. Boolean showzero;
  199. char numstr[32];
  200. short dec, digit;
  201. short work;
  202. Handle strHandle;
  203. char *sub1;
  204. char *sub2;
  205. short sub1len;
  206. short sub2len;
  207.     
  208.     
  209.     /* Allocate a record on the system heap to contain both the notification */
  210.     /* manager record and the error string: */
  211.     
  212.     recPtr = (NMRec *) NewPtrSys(sizeof(NMRec) + 256);
  213.     
  214.     if (recPtr != (NMRec *) 0)
  215.         {
  216.  
  217.         /* Generate a string containing the error code (signed): */
  218.         
  219.         n = numstr;
  220.         numlen = 0;
  221.         work = err;
  222.         if (work < 0)
  223.             {
  224.             *n++ = '-';
  225.             numlen++;
  226.             work = (-work);
  227.             }
  228.         dec = 10000;
  229.         showzero = false;
  230.         while (dec > 0)
  231.             {
  232.             digit = work / dec;
  233.             work = work % dec;
  234.             if ((digit != 0) || showzero)
  235.                 {
  236.                 showzero = true;
  237.                 *n++ = digit + '0';
  238.                 numlen++;
  239.                 }
  240.             if (dec > 1)
  241.                 dec = dec / 10;
  242.             else
  243.                 dec = 0;
  244.             }
  245.         
  246.         /* Get the string resource for the notification message ('STR '=0) */
  247.         /* and copy it into the allocated memory, along with the error code */
  248.         /* string.  The error code string is inserted in the message string */
  249.         /* where the first '%' character is found. */
  250.  
  251.         errstr = ((char *) recPtr) + sizeof(NMRec);
  252.         *errstr = 0;
  253.             
  254.         strHandle = GetResource('STR ', ResourceID);
  255.         
  256.         if (strHandle != nil)
  257.             {
  258.             
  259.             HLock(strHandle);
  260.             
  261.             /* Locate the '%' character, if any: */
  262.             
  263.             sub1 = (char *) *strHandle;
  264.             sub2 = sub1;
  265.             sub1len = *sub1++;
  266.             sub2len = sub1len;
  267.             if (sub1len > 0)
  268.                 sub2++;
  269.  
  270.             while ((*sub2 != '%') && (sub2len > 0))
  271.                 {
  272.                 sub2++;
  273.                 sub2len--;
  274.                 }
  275.             if (sub2len > 0)
  276.                 {
  277.                 sub2++; /* move past '%' if found */
  278.                 sub2len--;
  279.                 sub1len -= sub2len;
  280.                 sub1len--;
  281.                 }
  282.             
  283.             /* Build the error string */
  284.             
  285.             Append(errstr, sub1, sub1len);
  286.             Append(errstr, numstr, numlen);
  287.             Append(errstr, sub2, sub2len);
  288.  
  289.             /* Release the string resource */
  290.             
  291.             ReleaseResource(strHandle);
  292.             
  293.             }
  294.         
  295.         /* See if there is an additional string resource for this error: */
  296.         
  297.         strHandle = GetResource('STR ', (-err)); /* Use absolute value of error */
  298.         
  299.         if (strHandle != nil)
  300.             {
  301.             HLock(strHandle);
  302.             
  303.             Append(errstr, (char *) ((*strHandle) + 1), **strHandle);
  304.  
  305.             ReleaseResource(strHandle);
  306.  
  307.             }
  308.  
  309.         
  310.         /* Build the notification record and install it: */
  311.         /* NOTE: The memory block will be left abandoned on the System Heap!!! */
  312.         
  313.         if (*errstr != 0)
  314.             {
  315.             recPtr->qType = (short) nmType;
  316.             recPtr->nmMark = (short) 0;
  317.             recPtr->nmIcon = (Handle) nil;    // Formerly nmSIcon
  318.             recPtr->nmSound = (Handle) -1;
  319.             recPtr->nmStr = (StringPtr) errstr;
  320.             recPtr->nmResp = (NMProcPtr) -1;
  321.             recPtr->nmRefCon = (long) 0;
  322.             
  323.             (void) NMInstall(recPtr);
  324.             }
  325.         }
  326.     
  327.     return;
  328.     
  329. }
  330.  
  331. // These routines were taken from Tim Enwall's iacDriver in develop.
  332.  
  333. /**********************************Comment*****************************************
  334.  * lookForSlotInUnitTable returns a short corresponding to a valid "slot" number.  It'll
  335.  range from 48 to UnitNTryCnt.  If there are no slots available it returns 0.  Essentially what
  336.  we're doing here is starting at the END of the UnitTable, testing the value at each
  337.  long-word location to see if it's nil.  If it's nil, that means we can place our driver
  338.  at that location, so we'll return the value of the "slot".
  339.  **********************************End Comment************************************/
  340. short 
  341. lookForSlotInUnitTable()
  342. {
  343. short        slot;
  344. Ptr        theBass;
  345. long        *theVoidPtr;
  346. Boolean     foundSlot;
  347.  
  348.     slot = *((short *)(UnitNtryCnt)) - 1;
  349.     theBass = (Ptr) (*((long *) (UTableBase)));
  350.     
  351.     foundSlot = false;
  352.     
  353.     while(slot>48 && !foundSlot) 
  354.         {
  355.         theVoidPtr = (long *)(theBass + (4L * slot));
  356.         
  357.         if(*theVoidPtr == 0L)
  358.             foundSlot = true;
  359.             
  360.         slot -= 1;
  361.         }
  362.         
  363.     slot += 1;
  364.     
  365.     if(!foundSlot)
  366.         slot = 0;
  367.  
  368.     return slot;
  369. }
  370.  
  371.  
  372. /**********************************Comment*****************************************
  373. * changeDRVRSlot installs the driver into the slot passed in.  Because we want to keep
  374. * our DRVR resource ID in the resource file the same as it ever was, we GetResInfo on
  375. * it, and then set it back later.  But, before we set it back, we set the ID of the 
  376. * DRVR resource equal to the slot found, and then call OpenDriver.  OpenDriver uses the
  377. * resource ID of the DRVR resource to place it in the UnitTable -- pretty easy huh?
  378. * The only other tricky thing is we have to Detach the resource by calling DetachResource
  379. * so the resource doesn't go away when the resource file gets closed (the Resource
  380. * Manager is our friend).  The resource file gets closed when the INIT stops executing.
  381.  **********************************End Comment************************************/
  382. short changeDRVRSlot(short slot, StringPtr name)     /* Name is a pstring */
  383. {
  384. Handle            theDRVR;
  385. short            err, refNum;
  386. char            DRVRname[256];
  387. short            DRVRid;
  388. ResType            DRVRType;
  389.  
  390. if(slot != 0) 
  391.     {        
  392.         theDRVR = GetNamedResource('DRVR', name);
  393.         if (theDRVR)
  394.         {
  395.             GetResInfo(theDRVR, &DRVRid, &DRVRType, &DRVRname);
  396.             SetResInfo(theDRVR, slot, 0L);
  397.              
  398.             err = OpenDriver(name, &refNum);
  399.             if(err == noErr)
  400.                 {
  401.                 /* detach the resources from the resource map */
  402.                     DetachResource(theDRVR);
  403.          
  404.                 }
  405.             /* Restores the previous resource attributes so they don't change
  406.              * from startup to startup.  We just want the in-memory copy to have
  407.              * a different ID number -- not our resource in the file        */
  408.             theDRVR = GetNamedResource('DRVR', name);
  409.             SetResInfo(theDRVR, DRVRid, nil);
  410.         } else err = resNotFound;
  411.     }
  412.     return err;
  413. }
  414.  
  415. /**********************************Comment*****************************************
  416.  * InstallDriver installs a driver safely.  Taken from iacDriver example.
  417.  * it looks for a "slot" in the UnitTable into which the driver can be placed.  If
  418.  * it finds a "slot" it calls the procedure changeDRVRSlot to install the driver 
  419.  * into that slot.
  420.  **********************************End Comment************************************/
  421.  
  422. short InstallDriver(StringPtr drvrName)
  423. {
  424. short        tsSlot;
  425. short         err;
  426.  
  427.     if((tsSlot = lookForSlotInUnitTable()) != 0)
  428.         err = changeDRVRSlot(tsSlot, drvrName);
  429.     else err = unitTblFullErr;
  430.     
  431.     return err;
  432. }
  433.  
  434. // Given open Tracks driver, this will start it using users preferences..
  435. short InvokeTrace(short TraceRefNum,short prefsFolderRefNum, saveTypeHandle    hSave, Handle drvrName)
  436. {
  437. TraceParamBlock param;
  438. register short result, iconToUse;
  439. Boolean        WarnOfAutoWrite = false;
  440. Handle    PStrHand;    
  441.  
  442.     iconToUse = TracingIconID;
  443.     if (drvrName == nil)
  444.         {
  445.             return ErrorIconID;
  446.         }
  447.     
  448.     PStrHand = GetResource('STR ', -4063);
  449.     if (PStrHand == nil) 
  450.     {
  451.         return ErrorIconID;
  452.     }
  453.  
  454.     if ( (**hSave).Version != kVersionNumber) return ErrorIconID;    // Version Error 
  455.     HLock((Handle)hSave);
  456.     
  457.     //    **** Setup buffer area ****
  458.     if ((**hSave).fBufferSize== nil) 
  459.     {
  460.         InitNotify(smNilsBlockErr,2);    // Couldn't allocate requested memory....    
  461.         return ErrorIconID;
  462.     }
  463.     param.u.enable.traceBuffSize = (**hSave).fBufferSize & 0x0000FFFe;        /* Size of buffer (LIMITED TO 32K!)    */
  464.     param.u.enable.traceBuffSizeIndex = (**hSave).fCurrentSizeIndex;            /* Points to correct value */
  465.     result = Control(TraceRefNum, kEnableTraceBuffer, (Ptr) ¶m);
  466.     if (result != noErr) 
  467.     {
  468.         //InitNotify(result,2);    // Couldn't allocate requested memory....    
  469.         return ErrorIconID;
  470.     }
  471.  
  472.     // **** Handle File Name ****
  473.     param.u.enableFile.fileName = (char *)*PStrHand;
  474.     param.u.enableFile.vRefNum = prefsFolderRefNum;        // Into sys folder        
  475.     result = Control(TraceRefNum, kSetTraceFileName, (Ptr) ¶m);
  476.     if (result != noErr) 
  477.     {
  478.         return ErrorIconID;
  479.     }
  480.  
  481.     // **** Change Periodic write to file ****
  482.     // This will set the dNeedTime bit.
  483.     if ((**hSave).fAutoWriteOn)
  484.         result = Control(TraceRefNum, kSetAutoWriteOn, nil);
  485.     else
  486.         result = Control(TraceRefNum, kSetAutoWriteOff, nil);
  487.         
  488.     if (result != noErr) iconToUse = ErrorIconID; 
  489.     
  490.     result = Control(TraceRefNum,kStartedFromInit,(Ptr)true);
  491.     if (result != noErr) iconToUse = ErrorIconID; 
  492.     //    **** Set Break and Trace Masks ****
  493.     BlockMove((Ptr)(**hSave).fBreakMask,(Ptr)param.u.mask.Mask,16L);
  494.     param.u.mask.BreakOnce = (**hSave).fBreakOnceThenClear;    
  495.  
  496.     result = Control(TraceRefNum, kGetCdevBreakMask, (Ptr) ¶m);
  497.     if (result == noErr) 
  498.         BlockMove((Ptr)(**hSave).fTraceMask,(Ptr)param.u.mask.Mask,16L);
  499.  
  500.     result = Control(TraceRefNum, kGetCdevTraceMask, (Ptr) ¶m);
  501.     if (result != noErr) iconToUse = ErrorIconID; 
  502.  
  503.     // Turn Tracing On
  504.     
  505.     if ((**hSave).fTraceOnStartup && iconToUse != ErrorIconID)
  506.         {
  507.             result = Control(TraceRefNum, kSetTraceOnline, *drvrName);
  508.             if (result == noErr && (**hSave).fAutoWriteOn)
  509.                 {InitNotify(1,1);}        // Warn user that Auto Write to disk is on.
  510.             if (result != noErr) iconToUse = ErrorIconID;
  511.         }
  512.     else if (iconToUse != ErrorIconID) iconToUse = InactiveIconID;
  513.  
  514.     HUnlock((Handle)hSave);
  515.     DisposHandle((Handle)hSave);
  516.     ReleaseResource(PStrHand);
  517.     return (iconToUse);
  518. }
  519. // Returns vrefnum of a folder type
  520. short GetFolderVol(OSType type)
  521. {
  522. WDPBRec        wdParamBlock;        /*param block to set up working directory*/
  523. short         result;
  524. short         prefVRef;
  525. long         prefDirID;
  526.  
  527.     result=FindFolder(kOnSystemDisk, type, true, &prefVRef, &prefDirID);
  528.     if (result == 0)
  529.     {
  530.         wdParamBlock.ioCompletion = NULL;
  531.         wdParamBlock.ioNamePtr = NULL;
  532.         wdParamBlock.ioVRefNum = prefVRef;
  533.         wdParamBlock.ioWDDirID = prefDirID;
  534.         result=PBOpenWD(&wdParamBlock, false);
  535.         if (result == 0)
  536.             return wdParamBlock.ioVRefNum;
  537.     }
  538.     return 0;
  539. }
  540.